
package com.ruoyi.business.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.ruoyi.bizsys.domain.*;
import com.ruoyi.bizsys.dto.UserInfo;
import com.ruoyi.bizsys.enums.AwardEventEnum;
import com.ruoyi.bizsys.enums.AwardMethodEnum;
import com.ruoyi.bizsys.enums.UserStatusEnum;
import com.ruoyi.bizsys.service.*;
import com.ruoyi.bizsys.utils.UserCacheService;
import com.ruoyi.business.domain.ActivityAggregateVo;
import com.ruoyi.business.domain.DistributionAwardRecord;
import com.ruoyi.business.mapper.DistributionAwardRecordMapper;
import com.ruoyi.business.service.IAwardDistributionService;
import com.ruoyi.business.service.IAwardService;
import com.ruoyi.common.constant.ApplyConstants;
import com.ruoyi.common.utils.DateUtils;
import com.ruoyi.common.utils.DesensitizeUtils;
import com.ruoyi.common.utils.Func;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.uuid.IdUtils;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

/**
 * @author cyh
 * @date 2022/6/25 3:49 下午
 */
@Slf4j
@Service
@AllArgsConstructor
public class AwardDistributionServiceImpl extends BaseService implements IAwardDistributionService {

    private IAppUserService appUserService;

    private IAwardService awardService;

    private IUserActivityGroupService activityGroupService;

    private ICreditApplyService creditApplyService;

    private ICustomerInfoService customerInfoService;

    private ILoanIouService loanIouService;

    private IRealNameAuthService realNameAuthService;

    private UserCacheService userCacheService;

    private final DistributionAwardRecordMapper distributionAwardRecordMapper;

    @Override
    public JSONObject getUserActivityDetail() {

        AppUser appUser = webGetAppUser();
        JSONObject responseJson = new JSONObject();
        //获取活动信息
        ActivityAggregateVo awardActivityDetail = awardService.getAwardActivityDetail();
        //是否有活动
        responseJson.put("activityValidity", Func.isNotEmpty(awardActivityDetail));
        if (Func.isEmpty(awardActivityDetail)) return responseJson;
        //当前代理人权益是否激活
        boolean distributionQualification = distributionQualification(awardActivityDetail, appUser.getUserUuid(), appUser.getInviteCodeStatus());
        responseJson.put("distributionQualification", distributionQualification);
        //用户下级人数
        responseJson.put("inviteRelationCount", appUserService.inviteRelationCount(appUser.getInviteCode()) + "");
        //可提现的奖励金
        responseJson.put("awardAmountSum", awardService.getAwardAmountSum(appUser.getUserUuid()).toString());
        //奖励配置
        List<AwardConfig> awardConfigs = getAwardConfigs(awardActivityDetail.getAwardConfigs(), awardActivityDetail.getDistributionRatio().getFirstRatio());
        responseJson.put("eventList", awardConfigs);
        //用户邀请信息
        JSONObject inviteInfo = appUserService.getInviteInfo(appUser.getUserUuid());
        responseJson.put("inviteLink", inviteInfo.getString("inviteLink"));
        responseJson.put("inviteCode", inviteInfo.getString("inviteCode"));
        return responseJson;
    }

    private List<AwardConfig> getAwardConfigs(List<AwardConfig> awardConfigs, Integer firstRatio) {
        BigDecimal ratio = new BigDecimal(String.valueOf(firstRatio)).multiply(new BigDecimal("0.01"));
        awardConfigs.forEach(e -> {
            //如果是比例,取配置的金额*一级分销比例
            if (AwardMethodEnum.CASH_RATIO.getEventValue().equals(e.getAwardMethod())) {
                //现金比例
                BigDecimal cashRatio = new BigDecimal(String.valueOf(e.getAwardValue())).multiply(new BigDecimal("0.01"));
                e.setAwardValue(e.getProportionalAmount().multiply(cashRatio).multiply(ratio).intValue());
            }
            //如果是现金，现金*一级分销比例
            if (AwardMethodEnum.CASH.getEventValue().equals(e.getAwardMethod())) {
                //分销比例
                e.setAwardValue(new BigDecimal(String.valueOf(e.getAwardValue())).multiply(ratio).intValue());
            }
        });
        return awardConfigs;
    }


    @Override
    public JSONObject getAwardRecord(String userId) {
        return awardService.getUserRecord(userId);
    }

    @Override
    public JSONObject getAwardInviteFlow(String userId) {
        String inviteCode = getAppUser(userId).getInviteCode();

        //邀请人奖励记录
        JSONObject inviteRecords = awardService.getUserInviteRecord(userId);
        //获取所有下级联系人及其状态、注册时间、号码、奖励金
        List<AppUser> inviteRelationList = appUserService.inviteRelation(inviteCode);
        List<JSONObject> resList = new ArrayList<>();
        inviteRelationList.forEach(e -> {
            JSONObject awardMap = inviteRecords.getJSONObject(e.getUserUuid());
            //不存在奖励
            if (Func.isEmpty(awardMap)) {
                awardMap = new JSONObject();
                awardMap.put("invitedPhone", e.getPhone());
                awardMap.put("awardAmount", BigDecimal.ZERO);
                awardMap.put("invitedUserId", e.getUserUuid());

            }
            awardMap.put("createTime", DateUtils.parseDateToStr(DateUtils.YYYY_MM_DD_HH_MM_SS, e.getCreateTime()));
            awardMap.put("current_state", this.getUserCurrentStatus(e.getUserUuid()));
            awardMap.put("invitedPhone", DesensitizeUtils.around(awardMap.getString("invitedPhone"), 3, 4));
            resList.add(awardMap);
        });


        JSONObject inviteFlow = new JSONObject();
        inviteFlow.put("inviteList", resList);
        inviteFlow.put("inviteRelationCount", appUserService.inviteRelationCount(inviteCode));
        return inviteFlow;
    }

    //    @PostConstruct
    public void doTest() {
        String invitedUserId = "0178d9ccf2cf4978bc1007f2d3ab1579";
        distributionAwardTrigger(AwardEventEnum.REAL_NAME_SUCCESS, invitedUserId, new BigDecimal("123"));
    }

    /**
     * 奖励触发
     *
     * @param eventEnum     活动事件
     * @param invitedUserId 受邀人userId
     * @param awardAmount
     */
    @Async("threadPoolTaskExecutor")
    public void distributionAwardTrigger(AwardEventEnum eventEnum, String invitedUserId, BigDecimal awardAmount) {
        log.info("distributionAwardTrigger params => eventEnum:{}, invitedUserId:{}, awardAmount:{}", eventEnum.getEventValue(), invitedUserId, awardAmount);
        Long recordId = this.insertDistribution(eventEnum, invitedUserId, awardAmount);
        //查询有没有邀请码
        UserInfo invitedUserInfo = userCacheService.getUserInfoByUserId(invitedUserId);
        if (StringUtils.isEmpty(invitedUserInfo.getRecommendCode())) {
            this.updateDistributionState(recordId, "2", "被邀请人没有邀请码");
            return;
        }
        //获取活动信息
        ActivityAggregateVo awardActivityDetail = awardService.getAwardActivityDetail();
        if (Func.isEmpty(awardActivityDetail)) {
            this.updateDistributionState(recordId, "2", "获取活动详情为空");
            return;
        }
        //获取当前活动事件
        AwardConfig awardConfig = getCurrentActiveEvent(eventEnum, awardActivityDetail.getAwardConfigs());
        if (awardConfig == null) {
            this.updateDistributionState(recordId, "2", "获取活动事件为空");
            return;
        }
        log.info("eventType:{},活动事件:{}", eventEnum.getEventValue(), JSON.toJSONString(awardConfig));
        int rewardedCount = awardService.rewardedTotal(invitedUserInfo.getBvnNumber(), awardActivityDetail.getAwardActivity().getId(), awardConfig.getId());
        log.info("已奖励次数 {} >= 事件奖励次数 {}", rewardedCount, awardConfig.getAwardNum());
        //已奖励次数 >= 事件奖励次数
        if (rewardedCount >= awardConfig.getAwardNum()) {
            this.updateDistributionState(recordId, "2", "奖励次数限制");
            return;
        }
        //计算奖励金额
        BigDecimal awardPrincipal = AwardMethodEnum.conversion(awardConfig, awardAmount);
        //根据分销层级获取上级联系人
        List<AwardRecord> recordList = inviteSuperiorRelation(awardActivityDetail, invitedUserInfo, awardPrincipal, awardConfig);
        //向Award发送奖励记录，Award发送事务消息
        if (CollectionUtils.isEmpty(recordList)) {
            this.updateDistributionState(recordId, "2", "没有组装到分销奖励");
            return;
        }
        awardService.awardDistribution(recordList, recordId);
    }

    private Long insertDistribution(AwardEventEnum eventEnum, String invitedUserId, BigDecimal awardAmount) {
        DistributionAwardRecord distributionAwardRecord = new DistributionAwardRecord();
        distributionAwardRecord.setType(eventEnum.getEventValue());
        distributionAwardRecord.setInvitedUserId(invitedUserId);
        distributionAwardRecord.setAwardAmount(awardAmount);
        distributionAwardRecordMapper.insert(distributionAwardRecord);
        return distributionAwardRecord.getId();
    }

    private void updateDistributionState(Long recordId, String state, String remark) {
        DistributionAwardRecord distributionAwardRecord = new DistributionAwardRecord();
        distributionAwardRecord.setId(recordId);
        distributionAwardRecord.setState(state);
        distributionAwardRecord.setRemark(remark);
        distributionAwardRecordMapper.updateById(distributionAwardRecord);
    }

    private List<AwardRecord> inviteSuperiorRelation(ActivityAggregateVo awardActivityDetail, UserInfo invitedUserInfo, BigDecimal awardPrincipal, AwardConfig awardConfig) {

        //分销层级
        AwardDistributionRatio distributionRatio = awardActivityDetail.getDistributionRatio();
        //活动分组
        List<String> activityGroups = awardActivityDetail.getGroups();
        List<AwardRecord> recordList = new ArrayList<>();
        String recommendCode = invitedUserInfo.getRecommendCode();
        String batchNO = IdUtils.reqId();
        for (int i = 0; i < distributionRatio.getLevel(); i++) {
            if (StringUtils.isEmpty(recommendCode)) {
                continue;
            }
            //获取上级关系人
            AppUser superior = appUserService.getSuperior(recommendCode);
            if (superior == null) {
                continue;
            }
            recommendCode = superior.getRecommendCode();
            //非正常状态的代理人用户不获得奖励
            if(!superior.getState().equals(UserStatusEnum.NORMAL.getCode())){
                continue;
            }
            //判断是否在分组内
            boolean qualification = distributionQualification(awardActivityDetail, superior.getUserUuid());
            if (!qualification) continue;
            //当前层级的分润
            BigDecimal levelAwardPrincipal = distributionRatio.tieredBonus(awardPrincipal, i + 1);
            String serialNo = IdUtils.reqId();
            AwardRecord record = getAwardRecord(awardActivityDetail.getAwardActivity().getId(), invitedUserInfo, awardConfig, superior, levelAwardPrincipal, serialNo);
            record.setBatchNo(batchNO);
            recordList.add(record);
        }
        return recordList;
    }

    private AwardRecord getAwardRecord(Long actId, UserInfo invitedUserInfo, AwardConfig awardConfig, AppUser superior, BigDecimal levelAwardPrincipal, String serialNo) {
        RealNameAuth realNameAuth = realNameAuthService.getOneByUserId(superior.getUserUuid());
        String custNo = "";
        String bvnAccount = "";
        String lastName = "";
        if (realNameAuth != null) { //有实名信息则记录实名信息
            custNo = realNameAuth.getCustNo();
            bvnAccount = realNameAuth.getBvnAccount();
            lastName = realNameAuth.getLastName();
        } else { //否则只记录客户信息
            CustomerInfo customerInfo = customerInfoService.getOneByUserId(superior.getUserUuid());
            custNo = customerInfo.getCustNo();
            lastName = "user"; //写死 user
        }
        AwardRecord record = new AwardRecord();
        record.setSerialNo(serialNo);
        record.setUserId(superior.getUserUuid());
        record.setCustNo(custNo);
        record.setRealBvn(bvnAccount);
        record.setLastName(lastName);
        record.setRegisterPhone(superior.getPhone());
        record.setAwardAmount(levelAwardPrincipal);
        record.setInvitedPhone(invitedUserInfo.getRegisterPhone());
        record.setInvitedUserId(invitedUserInfo.getUserId());
        record.setInvitedBvn(invitedUserInfo.getBvnNumber());
        record.setActId(actId);
        record.setAwardConfigId(awardConfig.getId());
        record.setInvitedEventType(awardConfig.getAwardEventType());
        record.setInvitedEventAwardNum(awardConfig.getAwardNum());
        record.setInvitedEventAwardMethod(awardConfig.getAwardMethod());
        record.setInvitedEventAwardValue(awardConfig.getAwardValue());
        return record;
    }

    /**
     * 获取当前事件
     *
     * @param eventEnum
     * @param awardConfigs
     */
    private AwardConfig getCurrentActiveEvent(AwardEventEnum eventEnum, List<AwardConfig> awardConfigs) {
        for (AwardConfig awardConfig : awardConfigs) {
            if (eventEnum.getEventValue().equals(awardConfig.getAwardEventType())) return awardConfig;
        }
        return null;
    }

    /**
     * 用户经销资格
     *
     * @param awardActivityDetail
     * @param userId
     * @return
     */
    private boolean distributionQualification(ActivityAggregateVo awardActivityDetail, String userId, String inviteCodeStatus) {
        log.info("校验用户经销资格 >>> awardActivityDetail = {}，userId = {}, inviteCodeStatus = {}", awardActivityDetail, userId, inviteCodeStatus);

        if (StringUtils.equals("0", inviteCodeStatus)) {
            log.warn("用户邀请码已被冻结，无代理权益");
            return false;
        }

        //所有人可参与
        boolean anyone = awardActivityDetail.getAwardActivity().getActCondition().equals("0");
        if (anyone) return anyone;
        //获取组
        UserActivityGroup group = activityGroupService.getByUserId(userId);
        //是否在活动分组内
        boolean flag = (Func.isNotEmpty(group) && awardActivityDetail.getGroups().contains(group.getAwardGroupCode()));
        log.info("用户经销资格为：{}", flag);
        return flag;
    }

    /**
     * 用户经销资格
     *
     * @param awardActivityDetail
     * @param userId
     * @return
     */
    private boolean distributionQualification(ActivityAggregateVo awardActivityDetail, String userId) {
        //所有人可参与
        boolean anyone = awardActivityDetail.getAwardActivity().getActCondition().equals("0");
        if (anyone) return anyone;
        //获取组
        UserActivityGroup group = activityGroupService.getByUserId(userId);
        //是否在活动分组内
        return (Func.isNotEmpty(group) && awardActivityDetail.getGroups().contains(group.getAwardGroupCode()));
    }

    /**
     * 获取用户当前状态
     *
     * @param userId
     * @return
     */
    private String getUserCurrentStatus(String userId) {
        //未实名
        RealNameAuth realNameAuth = realNameAuthService.getOneByUserId(userId);
        if (Func.isEmpty(realNameAuth)) {
            return "Credit limit not checked";
        }
        //未提交授信
        CreditApply creditApply = creditApplyService.getOneByUserId(userId);
        if (Func.isEmpty(creditApply)) {
            return "Credit limit not checked";
        }
        //授信未完成
        if (!creditApply.getApplyStatus().equals(ApplyConstants.APPLY_STATE_PASS)) {
            return "Credit not completed";
        }
        String custNo = customerInfoService.getCustNoByUserId(userId);
        //未提现
        LoanIou loanIou = loanIouService.getLatestOne(custNo);
        if (Func.isEmpty(loanIou) || loanIou.getIouStatus().equals(LoanIou.LOAN_IOU_STATUS_SETTLE)) {
            return "No loan withdrawal";
        }
        //提现成功未还款
        return "Loan outstanding";

    }

}

